#pragma once
#include "simple_c_lexer.h"
#include <map>
#include <string>
#include <vector>

struct gl_header_syntax_error{
public:
	gl_header_syntax_error(const std::string &e) : m_Error(e) {}
	std::string m_Error;
};

class gl_header_parser{
public:
	gl_header_parser(simple_c_lexer &l) : m_Lexer(l), m_Look(kUndefined, "", -1) {}
	void parse();
	void dump(std::ostream &out);

private:
	void dump_groups(std::ostream &out);
	void move();
	void error(const std::string &a_Error);
	void unexpected(simple_c_tokens a_Expected, simple_c_tokens a_Current);
	void match(simple_c_tokens tag);
	void match_numeral();
	bool silent_match(simple_c_tokens tag);
	bool silent_match(simple_c_tokens tag, std::string &outlexeme);

	std::string get_type();

	std::string m_Prepend;
	simple_c_lexer m_Lexer;
	token m_Look;

	struct constant{
		std::string m_Name;
		std::string m_Value;
		std::string m_Type;
		bool m_IsLiteral;
	};

	struct parameter{
		std::string m_Full;
		std::string m_Name;
	};

	struct function{
		std::string m_ReturnType;
		std::string m_Name;
		std::vector<parameter> m_Parameters;
	};

	struct reference{
		enum ref_type{
			all,
			tokens_only,
			entry_points,
		} m_Type;

		std::string m_Category;
	};

	struct info{
	public:
		std::vector<constant> m_Constants;
		std::vector<reference> m_Reference;
		std::vector<function> m_Functions;

	};

	std::map<std::string, constant> m_AllConstants;
	std::map<std::string, info> m_Extensions;

	void parse_functions(info &i);
	void parse_const_cat(info &i);
};